package com.runa.rccprotocol.dto.runa;

import com.runa.protocol.dto.DtuHDRequestData;
import com.runa.protocol.dto.IResponseData;
import com.runa.protocol.util.ByteUtil;
import com.runa.protocol.util.DigitalUtil;
import com.runa.rccprotocol.dto.ConcentratorRequestData;
import lombok.extern.slf4j.Slf4j;

import java.io.UnsupportedEncodingException;

@Slf4j
public class RunaDeviceRequestData extends ConcentratorRequestData {

    private byte[] requestData;

    public RunaDeviceRequestData() {
        super(null);
    }
    public RunaDeviceRequestData(String serial) {
        super(serial);
    }

    public void openCollector(String address, int channel) {
        requestData = new byte[8];
        requestData[0] = 0x69;
        requestData[1] = 0x55;
        requestData[2] = 1;
        requestData[3] = (byte) Integer.parseInt(address.substring(2, 4), 16);
        requestData[4] = (byte) Integer.parseInt(address.substring(0, 2), 16);
        requestData[5] = (byte) channel;
        requestData[6] = ByteUtil.sum(requestData, 0, 6);
        requestData[7] = 0x16;
        setHaveResult(true);
    }

    public void readHeatMeter(String meter) {
        requestData = new byte[16];
        requestData[0] = 0x68;
        requestData[1] = 0x25;
        requestData[2] = (byte) Integer.parseInt(meter.substring(6, 8), 16);
        requestData[3] = (byte) Integer.parseInt(meter.substring(4, 6), 16);
        requestData[4] = (byte) Integer.parseInt(meter.substring(2, 4), 16);
        requestData[5] = (byte) Integer.parseInt(meter.substring(0, 2), 16);
        requestData[6] = 0;
        requestData[7] = 0x4d;
        requestData[8] = 0x22;
        requestData[9] = 1;
        requestData[10] = 3;
        requestData[11] = 0x1f;
        requestData[12] = (byte) 0x90;
        requestData[13] = 0x12;
        requestData[14] = ByteUtil.sum(requestData, 0, 14);
        requestData[15] = 0x16;
        setHaveResult(true);
    }

    public void readHeatMeter(String meter,byte equCode,byte[] factoryCode,byte[] functionCode) {
        requestData = new byte[16];
        requestData[0] = 0x68;
        requestData[1] = equCode;
        requestData[2] = (byte) Integer.parseInt(meter.substring(6, 8), 16);
        requestData[3] = (byte) Integer.parseInt(meter.substring(4, 6), 16);
        requestData[4] = (byte) Integer.parseInt(meter.substring(2, 4), 16);
        requestData[5] = (byte) Integer.parseInt(meter.substring(0, 2), 16);
        requestData[6] = factoryCode[0];
        requestData[7] = factoryCode[1];
        requestData[8] = factoryCode[2];
        requestData[9] = 1;
        requestData[10] = 3;
        requestData[11] = functionCode[0];
        requestData[12] = functionCode[1];
        requestData[13] = 0x00;
        requestData[14] = ByteUtil.sum(requestData, 0, 14);
        requestData[15] = 0x16;
        setHaveResult(true);
    }

    public static void main(String[] args) {
        RunaDeviceRequestData runaDeviceRequestData = new RunaDeviceRequestData();
        runaDeviceRequestData.readHouseValve("23301301");
        System.out.println(ByteUtil.byteToHexString(runaDeviceRequestData.getData()));

    }

    public void readTyHeatMeter(String meter, byte equCode, byte[] factoryCode, byte[] functionCode) {
        requestData = new byte[20];
        int index = 0;
        requestData[index++] = (byte)0xFE;
        requestData[index++] = (byte)0xFE;
        requestData[index++] = (byte)0xFE;
        requestData[index++] = (byte)0xFE;

        requestData[index++] = 0x68;
        requestData[index++] = equCode;
        requestData[index++] = (byte) Integer.parseInt(meter.substring(6, 8), 16);
        requestData[index++] = (byte) Integer.parseInt(meter.substring(4, 6), 16);
        requestData[index++] = (byte) Integer.parseInt(meter.substring(2, 4), 16);
        requestData[index++] = (byte) Integer.parseInt(meter.substring(0, 2), 16);


        requestData[index++] = factoryCode[0];
        requestData[index++] = factoryCode[1];
        requestData[index++] = factoryCode[2];

        requestData[index++] = 1;
        requestData[index++] = 3;
        requestData[index++] = functionCode[0];
        requestData[index++] = functionCode[1];
        requestData[index++] = 0x00;

        requestData[index++] = ByteUtil.sum(requestData, 4, 14);
        requestData[index++] = 0x16;

        setHaveResult(true);
    }



    public void readHouseValve(String valve) {
        requestData = new byte[16];
        requestData[0] = 0x68;
        requestData[1] = (byte) 0x81;
        requestData[2] = (byte) Integer.parseInt(valve.substring(6, 8), 16);
        requestData[3] = (byte) Integer.parseInt(valve.substring(4, 6), 16);
        requestData[4] = (byte) Integer.parseInt(valve.substring(2, 4), 16);
        requestData[5] = (byte) Integer.parseInt(valve.substring(0, 2), 16);
        requestData[6] = 0;
        requestData[7] = 0x11;
        requestData[8] = 0x11;
        requestData[9] = 1;
        requestData[10] = 3;
        requestData[11] = 0x1f;
        requestData[12] = (byte) 0x90;
        requestData[13] = 0x12;
        requestData[14] = ByteUtil.sum(requestData, 0, 14);
        requestData[15] = 0x16;
        setHaveResult(true);
    }

    public void setHouseValveOpen(String valve, int open, boolean lock) {
        requestData = new byte[20];
        requestData[0] = 0x68;
        requestData[1] = (byte) 0x81;
        requestData[2] = (byte) Integer.parseInt(valve.substring(6, 8), 16);
        requestData[3] = (byte) Integer.parseInt(valve.substring(4, 6), 16);
        requestData[4] = (byte) Integer.parseInt(valve.substring(2, 4), 16);
        requestData[5] = (byte) Integer.parseInt(valve.substring(0, 2), 16);
        requestData[6] = 0;
        requestData[7] = 0x11;
        requestData[8] = 0x11;
        requestData[9] = 4;
        requestData[10] = 7;
        requestData[11] = 0x1f;
        requestData[12] = (byte) 0x90;
        requestData[13] = 0x12;
        requestData[14] = 5;
        requestData[15] = 2;
        requestData[16] = (byte) (lock ? 1 :0);
        requestData[17] = (byte) open;
        requestData[18] = ByteUtil.sum(requestData, 0, 18);
        requestData[19] = 0x16;
        setHaveResult(true);
    }

    public void setHouseValveOpenLimit(String valve, int down, int up) {
        requestData = new byte[20];
        requestData[0] = 0x68;
        requestData[1] = (byte) 0x81;
        requestData[2] = (byte) Integer.parseInt(valve.substring(6, 8), 16);
        requestData[3] = (byte) Integer.parseInt(valve.substring(4, 6), 16);
        requestData[4] = (byte) Integer.parseInt(valve.substring(2, 4), 16);
        requestData[5] = (byte) Integer.parseInt(valve.substring(0, 2), 16);
        requestData[6] = 0;
        requestData[7] = 0x11;
        requestData[8] = 0x11;
        requestData[9] = 4;
        requestData[10] = 7;
        requestData[11] = 0x1f;
        requestData[12] = (byte) 0x90;
        requestData[13] = 0x00;
        requestData[14] = 19;
        requestData[15] = 2;
        requestData[16] = (byte) (down & 0xff);
        requestData[17] = (byte) (up & 0xff);
        requestData[18] = ByteUtil.sum(requestData, 0, 18);
        requestData[19] = 0x16;
        setHaveResult(true);
    }

    public void setHouseValveTemp(String valve, Float temp, Boolean lock, Float up, Float down) {
        if (temp != null && lock != null && up != null && down != null) {
            setHouseValveTempAndLimit(valve, temp, lock, up, down);
        } else if (temp != null && lock != null) {
            setHouseValveTemp(valve, temp, lock);
        } else if (up != null && down != null) {
            setHouseValveTempLimit(valve, up, down);
        } else {
            log.info("温控下发参数错误: {} {} {} {} {}", valve, temp, lock, up, down);
        }
    }

    private void setHouseValveTemp(String valve, float temp, boolean lock) {
        requestData = new byte[21];
        requestData[0] = 0x68;
        requestData[1] = (byte) 0x81;
        requestData[2] = (byte) Integer.parseInt(valve.substring(6, 8), 16);
        requestData[3] = (byte) Integer.parseInt(valve.substring(4, 6), 16);
        requestData[4] = (byte) Integer.parseInt(valve.substring(2, 4), 16);
        requestData[5] = (byte) Integer.parseInt(valve.substring(0, 2), 16);
        requestData[6] = 0;
        requestData[7] = 0x11;
        requestData[8] = 0x11;
        requestData[9] = 4;
        requestData[10] = 8;
        requestData[11] = 0x1f;
        requestData[12] = (byte) 0x90;
        requestData[13] = 0x12;
        requestData[14] = 6;
        requestData[15] = 3;
        requestData[16] = (byte) (lock ? 1 :0);
        String tempStr = String.valueOf((int) (temp * 100));
        requestData[17] = (byte) Integer.parseInt(tempStr.substring(2), 16);
        requestData[18] = (byte) Integer.parseInt(tempStr.substring(0, 2), 16);

        requestData[19] = ByteUtil.sum(requestData, 0, 19);
        requestData[20] = 0x16;
        setHaveResult(true);
    }

    private void setHouseValveTempLimit(String valve, float up, float down) {
        requestData = new byte[22];
        requestData[0] = 0x68;
        requestData[1] = (byte) 0x81;
        requestData[2] = (byte) Integer.parseInt(valve.substring(6, 8), 16);
        requestData[3] = (byte) Integer.parseInt(valve.substring(4, 6), 16);
        requestData[4] = (byte) Integer.parseInt(valve.substring(2, 4), 16);
        requestData[5] = (byte) Integer.parseInt(valve.substring(0, 2), 16);
        requestData[6] = 0;
        requestData[7] = 0x11;
        requestData[8] = 0x11;
        requestData[9] = 4;
        requestData[10] = 9;
        requestData[11] = 0x1f;
        requestData[12] = (byte) 0x90;
        requestData[13] = 0x12;

        requestData[14] = 7;
        requestData[15] = 4;
        String upStr = String.valueOf((int) (up * 100));
        String dwStr = String.valueOf((int) (down * 100));
        requestData[16] = (byte) Integer.parseInt(upStr.substring(2), 16);
        requestData[17] = (byte) Integer.parseInt(upStr.substring(0, 2), 16);
        requestData[18] = (byte) Integer.parseInt(dwStr.substring(2), 16);
        requestData[19] = (byte) Integer.parseInt(dwStr.substring(0, 2), 16);

        requestData[20] = ByteUtil.sum(requestData, 0, 20);
        requestData[21] = 0x16;
        setHaveResult(true);
    }


    private void setHouseValveTempAndLimit(String valve, float temp, boolean lock, float up, float down) {
        requestData = new byte[27];
        requestData[0] = 0x68;
        requestData[1] = (byte) 0x81;
        requestData[2] = (byte) Integer.parseInt(valve.substring(6, 8), 16);
        requestData[3] = (byte) Integer.parseInt(valve.substring(4, 6), 16);
        requestData[4] = (byte) Integer.parseInt(valve.substring(2, 4), 16);
        requestData[5] = (byte) Integer.parseInt(valve.substring(0, 2), 16);
        requestData[6] = 0;
        requestData[7] = 0x11;
        requestData[8] = 0x11;
        requestData[9] = 4;
        requestData[10] = 14;
        requestData[11] = 0x1f;
        requestData[12] = (byte) 0x90;
        requestData[13] = 0x12;
        requestData[14] = 6;
        requestData[15] = 3;
        requestData[16] = (byte) (lock ? 1 :0);
        String tempStr = String.valueOf((int) (temp * 100));
        requestData[17] = (byte) Integer.parseInt(tempStr.substring(2), 16);
        requestData[18] = (byte) Integer.parseInt(tempStr.substring(0, 2), 16);
        requestData[19] = 7;
        requestData[20] = 4;
        String upStr = String.valueOf((int) (up * 100));
        String dwStr = String.valueOf((int) (down * 100));
        requestData[21] = (byte) Integer.parseInt(upStr.substring(2), 16);
        requestData[22] = (byte) Integer.parseInt(upStr.substring(0, 2), 16);
        requestData[23] = (byte) Integer.parseInt(dwStr.substring(2), 16);
        requestData[24] = (byte) Integer.parseInt(dwStr.substring(0, 2), 16);
        requestData[25] = ByteUtil.sum(requestData, 0, 25);
        requestData[26] = 0x16;
        setHaveResult(true);
    }

    public void readBuildValve(String valve) {
        requestData = new byte[16];
        requestData[0] = 0x68;
        requestData[1] = 0x71;
        requestData[2] = (byte) Integer.parseInt(valve.substring(6, 8), 16);
        requestData[3] = (byte) Integer.parseInt(valve.substring(4, 6), 16);
        requestData[4] = (byte) Integer.parseInt(valve.substring(2, 4), 16);
        requestData[5] = (byte) Integer.parseInt(valve.substring(0, 2), 16);
        requestData[6] = 0;
        requestData[7] = 0x11;
        requestData[8] = 0x11;
        requestData[9] = 1;
        requestData[10] = 3;
        requestData[11] = 0x1f;
        requestData[12] = (byte) 0x90;
        requestData[13] = 0;
        requestData[14] = ByteUtil.sum(requestData, 0, 14);
        requestData[15] = 0x16;
        setHaveResult(true);
    }

    public void setBuildValveOpen(String valve, int open) {
        requestData = new byte[20];
        requestData[0] = 0x68;
        requestData[1] = 0x71;
        requestData[2] = (byte) Integer.parseInt(valve.substring(6, 8), 16);
        requestData[3] = (byte) Integer.parseInt(valve.substring(4, 6), 16);
        requestData[4] = (byte) Integer.parseInt(valve.substring(2, 4), 16);
        requestData[5] = (byte) Integer.parseInt(valve.substring(0, 2), 16);
        requestData[6] = 0;
        requestData[7] = 0x11;
        requestData[8] = 0x11;
        requestData[9] = 4;
        requestData[10] = 7;
        requestData[11] = 0x1f;
        requestData[12] = (byte) 0x90;
        requestData[14] = 1;
        requestData[15] = 2;
        requestData[16] = (byte) (open >> 8);
        requestData[17] = (byte) open;
        requestData[18] = ByteUtil.sum(requestData, 0, 18);
        requestData[19] = 0x16;
        setHaveResult(true);
    }

    public void setBuildValveModel(String valve, boolean model) {
        requestData = new byte[20];
        requestData[0] = 0x68;
        requestData[1] = 0x71;
        requestData[2] = (byte) Integer.parseInt(valve.substring(6, 8), 16);
        requestData[3] = (byte) Integer.parseInt(valve.substring(4, 6), 16);
        requestData[4] = (byte) Integer.parseInt(valve.substring(2, 4), 16);
        requestData[5] = (byte) Integer.parseInt(valve.substring(0, 2), 16);
        requestData[6] = 0;
        requestData[7] = 0x11;
        requestData[8] = 0x11;
        requestData[9] = 4;
        requestData[10] = 7;
        requestData[11] = 0x1f;
        requestData[12] = (byte) 0x90;
        requestData[14] = 3;
        requestData[15] = 2;
        requestData[17] = (byte) (model ? 1 : 0);
        requestData[18] = ByteUtil.sum(requestData, 0, 18);
        requestData[19] = 0x16;
        setHaveResult(true);
    }

    public void readElectricMeter(String meter) {
        requestData = new byte[19];
        requestData[0] = (byte) 0xfe;
        requestData[1] = (byte) 0xfe;
        requestData[2] = (byte) 0xfe;
        requestData[3] = 0x68;
        meter = String.format("%012d", Integer.parseInt(meter));
        ByteUtil.tenstringToBcd(requestData, meter, 4, false);
        requestData[10] = 0x68;
        requestData[11] = 0x11;
        requestData[12] = 4;
        requestData[13] = 0x33;
        requestData[14] = 0x32;
        requestData[15] = 0x34;
        requestData[16] = 0x33;
        requestData[17] = ByteUtil.sum(requestData, 3, 14);
        requestData[18] = 0x16;
        setHaveResult(true);
    }

    public void readBuildValve(int slave) {
        requestData = new byte[]{(byte) slave, 3, 0, 1, 0, 35, 0, 0};
        int crc = DigitalUtil.calcCrc16(requestData, 6);
        requestData[6] = (byte) (crc & 0xff);
        requestData[7] = (byte) (crc >> 8);
        setHaveResult(true);
    }

    public void setBuildValveOpen(int slave, int open) {
        requestData = new byte[]{(byte) slave, 16, 0, 1, 0, 1, 2, (byte) (open>>8), (byte) open, 0, 0};
        int crc = DigitalUtil.calcCrc16(requestData, 9);
        requestData[9] = (byte) (crc & 0xff);
        requestData[10] = (byte) (crc >> 8);
        setHaveResult(true);
    }

    public void setBuildValveLimit(int slave, int openUp, int openDw) {
        requestData = new byte[]{(byte) slave, 16, 0, 85, 0, 2, 4, (byte) (openDw>>8), (byte) openDw, (byte) (openUp>>8), (byte) openUp, 0, 0};
        int crc = DigitalUtil.calcCrc16(requestData, 11);
        requestData[11] = (byte) (crc & 0xff);
        requestData[12] = (byte) (crc >> 8);
        setHaveResult(true);
    }

    public void setBuildValveModel(int slave, boolean lr) {
        requestData = new byte[]{(byte) slave, 16, 0, 33, 0, 1, 2, 0, (byte) (lr ? 1 : 0), 0, 0};
        int crc = DigitalUtil.calcCrc16(requestData, 9);
        requestData[9] = (byte) (crc & 0xff);
        requestData[10] = (byte) (crc >> 8);
        setHaveResult(true);
    }

    @Override
    public boolean check(IResponseData data) {
        return true;
    }

    @Override
    public byte[] getData() {
        return requestData;
    }

    public void setData(byte[] bytes) {
        this.requestData = bytes;
    }
}
